﻿(function() {
    var DataMorph = window.DataMorph || {};

    DataMorph.PageViewModel = function(url) {
        var self = this;
        this.ClientId = "";
        
        this.StorageAccounts = ko.observableArray().extend({ dirty: false });
        this.StorageAccounts.loading = ko.observable(false);
        this.selectedAccount = ko.observable(null);
        this.selectedDataset = ko.observable(null);
        this.ProcessingTimes = ko.observableArray([]);
        this.ProcessingTimes.loading = ko.observable(false);
        this.DataSets = ko.observableArray().extend({ dirty: false });
        this.DataSets.loading = ko.observable(false);
        this.ClientId = ko.observable("");
        
        this.ProgressValue = ko.observable();
        this.ProgressMessage = ko.observable();
        this.Notification = ko.observable("");
        this.GeneratingData = ko.observable(false);
        this.ProcessingData = ko.observable(false);
        
        this.canGenerate = ko.computed(function() {
            return self.selectedDataset() != null && self.selectedDataset().newRecord();
        });
        
        this.canProcess = ko.computed(function () {
            return self.selectedDataset() != null && !self.selectedDataset().newRecord();
        });
        
        var dataMorphApi = new DataMorph.Api(url);

        this.Initialize = function () {
            self.StorageAccounts.loading(true);
            dataMorphApi.GetStorageAccounts(function(storageAccounts) {
                self.StorageAccounts.removeAll();
                var storageAccountsArray = ko.utils.arrayMap(storageAccounts,
                    function(storageAccount) {
                        var storageAccountViewModel = new DataMorph.StorageAccountViewModel(storageAccount.Name, storageAccount.Key);
                        return storageAccountViewModel;
                    });
                self.StorageAccounts(storageAccountsArray);
                self.StorageAccounts.loading(false);
            },
            displayError);
        };
        
        this.selectAccount = function (account) {
            self.DataSets.loading(true);
            self.selectedAccount(account);
            self.selectedDataset(null);
            dataMorphApi.GetDatasets(account.Name(), function (data) {
                account.DataSets.removeAll();
                var dataSetsArray = ko.utils.arrayMap(data, function(dataSet) {
                    var dataSetViewModel = new DataMorph.DatasetParametersViewModel(dataSet, self.processData);
                    return dataSetViewModel;
                });
                
                account.DataSets(dataSetsArray);
                self.DataSets.removeAll();
                self.DataSets(dataSetsArray);
                self.DataSets.loading(false);
            },
            displayError);
            
            // Load the run results table
            self.ProcessingTimes.loading(true);
            dataMorphApi.GetProcessingTimes(
                self.selectedAccount().Name(),
                function (processingResults) {
                    self.ProcessingTimes.removeAll();
                    var processingTimesArray = ko.utils.arrayMap(processingResults, function (result) {
                        var processingResult = new DataMorph.ProcessingTimesViewModel(result);
                        return processingResult;
                    });
                    self.ProcessingTimes(processingTimesArray);
                    self.ProcessingTimes.loading(false);
                },
                displayError
            );
        };

        this.addAccount = function() {
            self.StorageAccounts.push(new DataMorph.StorageAccountViewModel(null, null));
        };

        this.addDataset = function () {
            var newDataset = new DataMorph.DatasetParametersViewModel(null);
            newDataset.StorageAccountName(self.selectedAccount().Name());
            newDataset.StorageAccountKey(self.selectedAccount().Key());            
            self.DataSets.push(newDataset);
        };
        
        this.generateData = function (data) {
            self.selectedDataset(data);
            self.GeneratingData(true);
            self.Notification("Generating data");
            // Send in the client id as the payload.
            data.ClientId(self.ClientId());
            var dataToSend = ko.mapping.toJS(data);
            dataMorphApi.GenerateDataSet(dataToSend, null, displayError);
        };

        var displayError = function(message) {
            self.Notification(message);
            self.StorageAccounts.loading(false);
            self.ProcessingTimes.loading(false);
            self.DataSets.loading(false);
        };

        this.processData = function (dataSet) {
            self.ProcessingData(true);
            self.Notification("Processing data set");
            // Send in the client id as the payload.
            dataSet.ClientId(self.ClientId());
            var dataToSend = ko.mapping.toJS(dataSet);
            dataMorphApi.ProcessDataSet(dataToSend, displayError);
        };

        this.processingTitle = "";
        this.reverseSort = false;
        this.sortProcessedTimes = function (data, e) {
            if (!e.target.id) {
                return;
            }
            var title = e.target.id;
            if (self.processingTitle == title) {
                self.reverseSort = self.reverseSort ? false : true;
            }
            
            self.processingTitle = title;
                        
            self.ProcessingTimes.sort(function (left, right) {
                switch (title) {
                    case "DataSet":
                        return left.DataSet() == right.DataSet() ? 0 : (left.DataSet() < right.DataSet() ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "TimeRequested":
                        return left.TimeRequested() == right.TimeRequested() ? 0 : (moment(left.TimeRequested()).isBefore(right.TimeRequested()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "TotalProcessingTime":
                        return left.TimeRequested() == right.TimeRequested() ? 0 : (parseFloat(left.TotalProcessingTime()) < parseFloat(right.TotalProcessingTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "AverageParseTime":
                        return left.AverageParseTime() == right.AverageParseTime() ? 0 : (parseFloat(left.AverageParseTime()) < parseFloat(right.AverageParseTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "AverageWriteTime":
                        return left.AverageWriteTime() == right.AverageWriteTime() ? 0 : (parseFloat(left.AverageWriteTime()) < parseFloat(right.AverageWriteTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "MaxParseTime":
                        return left.MaxParseTime() == right.MaxParseTime() ? 0 : (parseFloat(left.MaxParseTime()) < parseFloat(right.MaxParseTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "MaxWriteTime":
                        return left.MaxWriteTime() == right.MaxWriteTime() ? 0 : (parseFloat(left.MaxWriteTime()) < parseFloat(right.MaxWriteTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "MinParseTime":
                        return left.MinParseTime() == right.MinParseTime() ? 0 : (parseFloat(left.MinParseTime()) < parseFloat(right.MinParseTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "MinWriteTime":
                        return left.MinWriteTime() == right.MinWriteTime() ? 0 : (parseFloat(left.MinWriteTime()) < parseFloat(right.MinWriteTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "CompletedTime":
                        return left.CompletedTime() == right.CompletedTime() ? 0 : (moment(left.CompletedTime()).isBefore(right.CompletedTime()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "InstanceCount":
                        return left.InstanceCount() == right.InstanceCount() ? 0 : (parseInt(left.InstanceCount()) < parseInt(right.InstanceCount()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "CoreCount":
                        return left.CoreCount() == right.CoreCount() ? 0 : (parseInt(left.CoreCount()) < parseInt(right.CoreCount()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                    case "BatchSize":
                        return left.BatchSize() == right.BatchSize() ? 0 : (parseInt(left.BatchSize()) < parseInt(right.BatchSize()) ? (self.reverseSort ? 1 : -1) : (self.reverseSort ? -1 : 1));
                };
                throw "Invalid column name";
            });
        };

        this.Refresh = function() {
            self.selectAccount(self.selectedAccount());
        };
    };
    
})();